<?php

class SpellCorrectorHash {
	private static $NWORDS;

	private static function edits1($word) {
		$alphabet = 'abcdefghijklmnopqrstuvwxyz';
		//$alphabet = 'аәбвгғдеёжзийкқлмнңоөпрстуұүфхһцчшщъыіьэюя';
		$alphabet = str_split($alphabet);
		$n = strlen($word);
		$edits = array();
		for($i = 0 ; $i<$n;$i++) {
			$edits[] = substr($word,0,$i).substr($word,$i+1); 		//deleting one char
			foreach($alphabet as $c) {
				$edits[] = substr($word,0,$i) . $c . substr($word,$i+1); //substituting one char
			}
		}
		for($i = 0; $i < $n-1; $i++) {
			$edits[] = substr($word,0,$i).$word[$i+1].$word[$i].substr($word,$i+2); //swapping chars order
		}
		for($i=0; $i < $n+1; $i++) {
			foreach($alphabet as $c) {
				$edits[] = substr($word,0,$i).$c.substr($word,$i); //inserting one char
			}
		}
		return $edits;
	}
	
	private static function known_edits2($word) {
		$known = array();
		foreach(self::edits1($word) as $e1) {
			foreach(self::edits1($e1) as $e2) {
				if(array_key_exists($e2,self::$NWORDS)) $known[$e2] = $e2;				
			}
		}
		return $known;
	}
	
	private static function known(array $words) {
		$known = array();
		foreach($words as $w) {
			if(array_key_exists($w,self::$NWORDS)) {
				$known[$w] = $w;
			}
		}
		return $known;
	}

	// dvoinye slova
	private static function okCheck($word) {
		$withoutOk = array();
		$okonchaniya = array("gan","gen","lar","ler","da","de");
		//$okonchaniya = array("ған","ген","қан","кен","да","де","та","те","лар","лер","тар","тер","дар","дер");
		foreach ($okonchaniya as $ok) {
			if(!(strpos($word,$ok)===false)){
				$withoutOk[]=substr($word, 0, strpos($word, $ok));
			}
		}
		$withoutOkVal = array();
		$withoutOkVal = array_values(self::known($withoutOk));
		return $withoutOkVal;
	}

	public static function correct($word) {
		$ret = array();
		$word = trim($word);
		if(empty($word)) return;	
		$word = strtolower($word);
		if(empty(self::$NWORDS)) {
			if(!file_exists('serialized_dictionary.txt')) {
				$hashmap = array(); 
				$query = Dictionary::model()->findAll();
				foreach ($query as $q) {
    				$hashmap[$q->word] = $q->stat;
    			} 
				self::$NWORDS = $hashmap;
				$fp = fopen("serialized_dictionary.txt","w+");
				fwrite($fp,serialize(self::$NWORDS));
				fclose($fp);
			} else {
				self::$NWORDS = unserialize(file_get_contents("serialized_dictionary.txt"));
			}
		}
		$candidates = array();
		$secondST = array();
		$secondST = self::okCheck($word); 
		if(self::known(array($word))) {
			$ret[]=$word;
			return $ret;
		}elseif($secondST){
			return $secondST;
		}elseif(($tmp_candidates = self::known_edits2($word))) {
			foreach($tmp_candidates as $candidate) {
				$candidates[] = $candidate;
			}
		}else {
			$ret[]=$word;
			return $ret;
		}
		return $candidates;
	}	
}

?>